package com.duanjc.mergemd.service;



import cn.hutool.core.io.FileUtil;
import com.duanjc.mergemd.bean.DocumentContent;
import com.duanjc.mergemd.constant.FileConsts;
import com.duanjc.mergemd.task.MergeTask;
import com.duanjc.mergemd.utils.FileCheckUtils;
import com.duanjc.mergemd.utils.FileIOUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 本类用于将源路径下的所有文件合并成多个文件
 *
 * @author cqh
 * @date 2022/03/13 17:52
 */
@Slf4j
@Service
public class MergeToMultipleFile extends AbstractMergeFile{
    /**
     * 生成多个文件时，文件名为源路径第几个层次下的目录名。<br>
     * <p>例：源路径为 E:\a，a 包括 a1、a2 目录，a1 包括 a11、a12 目录，a2 包括 a21 目录。
     *
     * <p>指定 level 为 2，fileSuffix 为 .md，生成的文件为 a11.md、a12.md、a21.md；
     * a11.md 是 a11 目录下所有 md 文件的集合，其它同理。
     *
     * <p>指定 level 为 1，fileSuffix 为 .md，生成的文件为 a1.md、a2.md；
     * a1.md 是 a1 目录下所有 md 文件的集合。
     */
    int level;

    /**
     * 记录指定层次下目录名的集合
     */
    List<String> fileNameList;

    /**
     * 记录源目录路径最后一个斜杆的下标，用于截取文件以及此文件所在的目录名
     */
    private int slantIndex;

    /**
     * 记录插入文件的个数，当写入第 fileCount 个文件前时插入 [TOC]，
     * fileCount 下标从 1 开始
     */
    private int fileCount;

    @Autowired
    private MergeTask mergeTask;

    /*public MergeToMultipleFile(DocumentContent fileContent) {
        this.suffix = fileContent.getSuffix();
        this.level = fileContent.getLevel();
        this.destPath = fileContent.getDestPath();
        this.srcPath = fileContent.getSrcPath();
    }*/


    /**
     * 在生成的每个文件的开头插入目录 [TOC]，如果文件已存在则先清空文件内容。
     *
     * @param bufferedWriter 使用此实例写入目录
     * @param dest           被写入的文件
     * @throws IOException 读取文件或写入失败抛出此异常
     */
    @Override
    public void insertToDirectory(BufferedWriter bufferedWriter, File dest) throws IOException {
        if (fileCount++ == 0) {
            FileIOUtils.clear(dest);
            bufferedWriter.write("[TOC]\n");
        }
    }

    /**
     * 将指定路径下的所有文件合并成多个文件
     *
     * @throws IOException 详看{@link AbstractMergeFile#mergeFile(File, File)}方法抛出的 {@code IOException} 说明
     */
    @Override
    public void operationMerge() throws IOException {
        if (!FileCheckUtils.isFileSuffix(suffix)) {
            log.error("后缀格式错误");
            return;
        }

        //判断输出目录是否存在，存在则删除
        File outDirectory = new File(this.destPath);
        if (FileUtil.isDirectory(outDirectory)) {
            log.info("输出目录已存在，进行清除！");
            FileUtil.clean(outDirectory);
        }

        //扫描一级目录,不会扫描子目录
        File[] files = FileUtil.ls(srcPath);
        CountDownLatch latch = new CountDownLatch(files.length);
        for (File file : files) {
            mergeTask.catalogMerge(file.getPath(), this.destPath, suffix, level, latch);
        }

        //合并图片
        mergeTask.copyPic(srcPath,destPath);


        /*// 属性初始化
        slantIndex = srcPath.length() - 1;
        if (!srcPath.endsWith(FileConsts.BACKSLASH)) {
            slantIndex++;
        }
        fileNameList = new ArrayList<>();

        File src = new File(srcPath);
        File dest = new File(destPath);

        // 获取 src 下指定层次的所有目录名，根据此目录名可以确定 dest
        getFileNameList(src, level);
        for (String fileName : fileNameList) {
            // 每次合并完一个文件后，将此值归 0
            fileCount = 0;
            String substring = fileName.substring(slantIndex);

            // 生成写入文件所在目录
            String destFileName = dest + substring;
            File parentFile = new File(destFileName).getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            mergeFile(new File(fileName), new File(destFileName + suffix));
        }
        System.out.println("合并了指定层次的文件！");*/
    }

    /**
     * description: setDocumentContent <br>
     * version: 1.0 <br>
     * date: 2022/11/24 17:59 <br>
     * author: duanjiangcheng <br>
     *
     * @param documentContent documentContent
     * @return void
     */
    @Override
    public void setDocumentContent(DocumentContent documentContent) {
        this.suffix = documentContent.getSuffix();
        this.level = documentContent.getLevel();
        this.destPath = documentContent.getDestPath();
        this.srcPath = documentContent.getSrcPath();
    }

    /**
     * 获取指定层次下的目录名
     *
     * @param src   源路径
     * @param level 指定层级
     */
    public void getFileNameList(File src, int level) {
        if (src.isDirectory()) {
            if (level == 0) {
                String absolutePath = src.getAbsolutePath();
                fileNameList.add(absolutePath);
                return;
            }
            for (File file : src.listFiles()) {
                getFileNameList(file, level - 1);
            }
        }
    }
}
